package com.fxm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fxm.constant.RedisConstants;
import com.fxm.dao.SignInMapper;
import com.fxm.domain.Sign;
import com.fxm.returns.RespCode;
import com.fxm.returns.RespEntity;
import com.fxm.service.SignInService;
import com.fxm.service.UserService;
import com.fxm.utils.RedisUtil;
import com.fxm.utils.TimeRatioUtil;
import com.fxm.vo.param.IntegralParam;
import com.fxm.vo.param.OpenParam;
import com.fxm.vo.result.SignResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户签到信息 服务实现类
 * </p>
 *
 * @author fxm
 * @since 2021-01-04
 */
@Slf4j
@Service
public class SignInServiceImpl extends ServiceImpl<SignInMapper, Sign> implements SignInService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserService userService;

    @Autowired
    private SignInService signInService;

    @Override
    public RespEntity<SignResult> getSignInValue(OpenParam openParam) {
        if (Objects.isNull(openParam)) {
            log.info("参数为空，不符合要求");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        String count = redisUtil.get(RedisConstants.key.getSignIn(openParam.getOpenid()));
        //累计签到天数
        count = StringUtils.isBlank(count) ? "0" : count;
        //今日签到可获积分
        Integer integral = rewardPoints(Integer.parseInt(count));
        log.info(openParam.getOpenid() + "用户的签到次数为，count={}", count);
        //数据组装
        SignResult signResult = dataPackage(count, integral);
        return new RespEntity(RespCode.SUCCESS, signResult);
    }

    @Override
    public RespEntity<SignResult> signIn(OpenParam openParam) {
        if (Objects.isNull(openParam)) {
            log.info("参数为空，不符合要求");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        //先查询之前的签到次数
        RespEntity<SignResult> respEntity = getSignInValue(openParam);
        if (Objects.isNull(respEntity.getData())) {
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        SignResult signResult = (SignResult) respEntity.getData();
        //累计签到次数
        int count = signResult.getDays() + 1;
        //当前时间到第二天凌晨的秒数
        Long nextEarlyMorningSeconds = TimeRatioUtil.getSecondsNextEarlyMorning();
        //新增或覆盖原有缓存记录并设置过期时间
        redisUtil.set(RedisConstants.key.getSignIn(openParam.getOpenid()), String.valueOf(count), nextEarlyMorningSeconds);
        log.info("签到成功，签到次数为，count={}", count);
        //当前时间到今天凌晨的秒数
        Long todayEarlyMorningSeconds = TimeRatioUtil.getSecondsTodayEarlyMorning();
        //标记为已签到并设置过期时间
        redisUtil.set(RedisConstants.key.getIsSign(openParam.getOpenid()),  "sign", todayEarlyMorningSeconds);
        //签到积分奖励
        Integer integral = rewardPoints(count);
        log.info("今日签到可获积分为，integral={}", integral);
        //更新用户积分值
        updateUserIntegral(integral, openParam.getOpenid());
        return new RespEntity(RespCode.SUCCESS, new SignResult(integral, count));
    }


    /**
     * 更新用户积分
     * @param integral
     * @param openid
     */
    private void updateUserIntegral(Integer integral, String openid) {
        IntegralParam integralParam = new IntegralParam();
        integralParam.setOpenid(openid);
        integralParam.setNumber(integral);
        userService.updateUser(integralParam);
    }

    /**
     * 积分奖励规则
     * @param count
     * @return
     */
    private Integer rewardPoints(Integer count) {
        if (count == 0) {
            return count;
        }
        //七天及以上 按照七天计算奖励
        if (count > 7) {
            count = 7;
        }
        QueryWrapper<Sign> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Sign::getDays, count)
                             .eq(Sign::getDeleted, 0);
        Sign sign = baseMapper.selectOne(queryWrapper);
        return sign.getReward();
    }

    /**
     * 数据组装
     * @param count
     * @param integral
     * @return
     */
    private SignResult dataPackage(String count, Integer integral) {
        SignResult signResult = new SignResult();
        signResult.setDays(Integer.parseInt(count));
        signResult.setScore(integral);
        List<Sign> signList = signInService.list();
        for (Sign sign : signList) {
            switch (sign.getDays()) {
                case 1 : signResult.setDay1(sign.getReward()); break;
                case 2 : signResult.setDay2(sign.getReward()); break;
                case 3 : signResult.setDay3(sign.getReward()); break;
                case 4 : signResult.setDay4(sign.getReward()); break;
                case 5 : signResult.setDay5(sign.getReward()); break;
                case 6 : signResult.setDay6(sign.getReward()); break;
                case 7 : signResult.setDay7(sign.getReward()); break;
            }
        }
        return signResult;
    }
}
